package com.gitee.ixtf.cqrs.internal

import com.gitee.ixtf.cqrs.Metadata
import com.gitee.ixtf.cqrs.client.ComponentMethodRef
import com.gitee.ixtf.cqrs.client.ComponentMethodRef1
import com.gitee.ixtf.cqrs.client.ComponentMethodRef2
import com.gitee.ixtf.cqrs.client.ComponentMethodRef3
import com.gitee.ixtf.cqrs.client.ComponentMethodRef4
import com.gitee.ixtf.cqrs.client.ComponentMethodRef5
import io.vertx.core.Future
import io.vertx.kotlin.coroutines.coAwait
import java.util.concurrent.CompletionStage
import kotlin.reflect.KFunction
import kotlin.reflect.full.callSuspend
import kotlinx.coroutines.reactor.mono

class ComponentMethodRefImpl(
    private val instanceFuture: Future<*>,
    private val methodRef: KFunction<*>,
) :
    ComponentMethodRef<Any?>,
    ComponentMethodRef1<Any?, Any?>,
    ComponentMethodRef2<Any?, Any?, Any?>,
    ComponentMethodRef3<Any?, Any?, Any?, Any?>,
    ComponentMethodRef4<Any?, Any?, Any?, Any?, Any?>,
    ComponentMethodRef5<Any?, Any?, Any?, Any?, Any?, Any?> {
  override fun withMetadata(metadata: Metadata): ComponentMethodRefImpl = this

  override fun invokeAsync(): CompletionStage<Any?> =
      mono {
            val instance = instanceFuture.coAwait()
            if (methodRef.isSuspend) methodRef.callSuspend(instance) else methodRef.call(instance)
          }
          .toFuture()

  override fun invokeAsync(a1: Any?): CompletionStage<Any?> =
      mono {
            val instance = instanceFuture.coAwait()
            if (methodRef.isSuspend) methodRef.callSuspend(instance, a1)
            else methodRef.call(instance, a1)
          }
          .toFuture()

  override fun invokeAsync(a1: Any?, a2: Any?): CompletionStage<Any?> =
      mono {
            val instance = instanceFuture.coAwait()
            if (methodRef.isSuspend) methodRef.callSuspend(instance, a1, a2)
            else methodRef.call(instance, a1, a2)
          }
          .toFuture()

  override fun invokeAsync(a1: Any?, a2: Any?, a3: Any?): CompletionStage<Any?> =
      mono {
            val instance = instanceFuture.coAwait()
            if (methodRef.isSuspend) methodRef.callSuspend(instance, a1, a2, a3)
            else methodRef.call(instance, a1, a2, a3)
          }
          .toFuture()

  override fun invokeAsync(a1: Any?, a2: Any?, a3: Any?, a4: Any?): CompletionStage<Any?> =
      mono {
            val instance = instanceFuture.coAwait()
            if (methodRef.isSuspend) methodRef.callSuspend(instance, a1, a2, a3, a4)
            else methodRef.call(instance, a1, a2, a3, a4)
          }
          .toFuture()

  override fun invokeAsync(
      a1: Any?,
      a2: Any?,
      a3: Any?,
      a4: Any?,
      a5: Any?
  ): CompletionStage<Any?> =
      mono {
            val instance = instanceFuture.coAwait()
            if (methodRef.isSuspend) methodRef.callSuspend(instance, a1, a2, a3, a4, a5)
            else methodRef.call(instance, a1, a2, a3, a4, a5)
          }
          .toFuture()
}
